#!/usr/bin/env python
import flowd
import sys
import string
import math
import getopt
import time
import datetime
import pickle
import gzip

class flow_stat_count:
	def __init__(self):
		self.flows = 0
		self.octets = 0
		self.packets = 0

	def update(self, flow):
		self.flows += 1
		if flow.has_field(flowd.FIELD_OCTETS):
			self.octets += flow.octets
		if flow.has_field(flowd.FIELD_PACKETS):
			self.packets += flow.packets		

class flow_statistic:
	def __init__(self):
		self.num_unique = 0
		self.counts = {}

	def update(self, what, flow):
		try:
			count = self.counts[what]
		except:
			self.num_unique += 1
			count = flow_stat_count()
			self.counts[what] = count

		count.update(flow)



class flow_statistics:
	def __init__(self):
		self.first = None
		self.last = None
		self.start = None
		self.finish = None
		self.time = None
		self.average_clockskew = None
		self.average_clockskew_samples = 0
		self.src_port = flow_statistic()
		self.dst_port = flow_statistic()
		self.port = flow_statistic()
		self.src_addr = flow_statistic()
		self.dst_addr = flow_statistic()
		self.fromto = flow_statistic()
		self.addr = flow_statistic()
		self.gateway_addr = flow_statistic()
		self.agent_addr = flow_statistic()
		self.protocol = flow_statistic()
		self.in_if = flow_statistic()
		self.out_if = flow_statistic()
		self.in_out_if = flow_statistic()
		self.src_as = flow_statistic()
		self.dst_as = flow_statistic()
		self.src_dst_as = flow_statistic()
		self.tos = flow_statistic()
		self.engine_id = flow_statistic()
		self.engine_type = flow_statistic()
		self.tag = flow_statistic()
		self.src_prefix = flow_statistic()
		self.dst_prefix = flow_statistic()
		self.src_dst_prefix = flow_statistic()
		self.flows = 0;
		self.octets = None;
		self.packets = None;
		self.packsize = flow_statistic()
		self.ppf = flow_statistic() # packets per flow
		self.opf = flow_statistic() # octets per flow
		self.k = 0;

	def update0(self, flow):
		self.flows += 1
		
		if flow.has_field(flowd.FIELD_RECV_TIME):
			
			if self.first is None or \
			   flow.recv_sec < self.first:
				self.first = flow.recv_sec
			if self.last is None or \
			   flow.recv_sec > self.last:
				self.last = flow.recv_sec
			if self.start is None or \
			   flow.flow_start < self.start:
				self.start = flow.flow_start
			if self.finish is None or \
			   flow.flow_finish > self.finish:
				self.finish = flow.flow_finish
			if self.time is None:
				self.time = flow.flow_finish - flow.flow_start
			if flow.has_field(flowd.FIELD_FLOW_TIMES):
				delta = flow.recv_sec - \
				    flow.flow_finish / 1000.0
				if self.average_clockskew is None:
					self.average_clockskew = delta
				self.average_clockskew_samples += 1
				new_offset = delta - self.average_clockskew
				self.average_clockskew += new_offset / \
				    self.average_clockskew_samples
				self.time += flow.flow_finish - flow.flow_start
				
		if flow.has_field(flowd.FIELD_OCTETS):
			if self.octets is None:
				self.octets = 0
			self.octets += flow.octets


		if flow.has_field(flowd.FIELD_PACKETS):
			if self.packets is None:
				self.packets = 0
			self.packets += flow.packets
			
	def update1(self, flow):
		if flow.has_field(flowd.FIELD_OCTETS) and \
		   flow.has_field(flowd.FIELD_PACKETS):
			if flow.packets != 0: 
				self.packsize.update((flow.octets / flow.packets), flow)
	
	def update2(self, flow):
		if flow.has_field(flowd.FIELD_PACKETS):
			if self.packets is None:
				self.packets = 0
			self.ppf.update(flow.packets, flow)
	
	def update3(self, flow):
		if flow.has_field(flowd.FIELD_OCTETS):
			if self.octets is None:
				self.octets = 0
			self.octets += flow.octets
			self.opf.update(flow.octets, flow)
	
	def update5(self, flow):
		if flow.has_field(flowd.FIELD_SRCDST_PORT):
			self.dst_port.update(flow.dst_port, flow)
	
	def update6(self, flow):
		if flow.has_field(flowd.FIELD_SRCDST_PORT):
			self.src_port.update(flow.src_port, flow)
	
	def update7(self, flow):
		if flow.has_field(flowd.FIELD_SRCDST_PORT):
			self.port.update(flow.src_port, flow)

		if flow.has_field(flowd.FIELD_SRCDST_PORT):
			self.port.update(flow.dst_port, flow)
	
	def update8(self, flow):
		if flow.has_field(flowd.FIELD_DST_ADDR):
			self.dst_addr.update(flow.dst_addr, flow)
	
	def update9(self, flow):
		if flow.has_field(flowd.FIELD_SRC_ADDR):
			self.src_addr.update(flow.src_addr, flow)
	
	def update10(self, flow):
		if flow.has_field(flowd.FIELD_SRC_ADDR) and \
		   flow.has_field(flowd.FIELD_DST_ADDR):
		   	fromto = flow.src_addr + " -> " + \
				 flow.dst_addr
			self.fromto.update(fromto, flow)
			self.src_dst_prefix.update(self.net(flow.src_addr, flow.src_mask)+"\t"+self.net(flow.dst_addr, flow.dst_mask), flow)
	
	def update11(self, flow):
		if flow.has_field(flowd.FIELD_SRC_ADDR):
			self.addr.update(flow.src_addr, flow)

		if flow.has_field(flowd.FIELD_DST_ADDR):
			self.addr.update(flow.dst_addr, flow)
	
	def update12(self, flow):
		if flow.has_field(flowd.FIELD_PROTO_FLAGS_TOS):
			self.protocol.update(flow.protocol, flow)
	
	def update15(self, flow):
		self.flows += 1
		
		if flow.has_field(flowd.FIELD_OCTETS):
			if self.octets is None:
				self.octets = 0
			self.octets += flow.octets

		if flow.has_field(flowd.FIELD_PACKETS):
			if self.packets is None:
				self.packets = 0
			self.packets += flow.packets
	
	def update16(self, flow):
		if flow.has_field(flowd.FIELD_GATEWAY_ADDR):
			self.gateway_addr.update(flow.gateway_addr, flow)
	
	def update17(self, flow):
		if flow.has_field(flowd.FIELD_IF_INDICES):
			self.in_if.update(flow.if_ndx_in, flow)
	
	def update18(self, flow):	
		if flow.has_field(flowd.FIELD_IF_INDICES):
			self.out_if.update(flow.if_ndx_out, flow)
	
	def update19(self, flow):
		if flow.has_field(flowd.FIELD_AS_INFO):
			self.src_as.update(flow.src_as, flow)
	
	def update20(self, flow):
		if flow.has_field(flowd.FIELD_AS_INFO):
			self.dst_as.update(flow.dst_as, flow)
	
	def update21(self, flow):
		if flow.has_field(flowd.FIELD_AS_INFO):
			srcdstas = "%d\t%d" %(flow.src_as, flow.dst_as)
			self.src_dst_as.update(srcdstas, flow)
	
	def update22(self, flow):
		if flow.has_field(flowd.FIELD_PROTO_FLAGS_TOS):
			self.tos.update(flow.tos, flow)
	
	def update23(self, flow):
		if flow.has_field(flowd.FIELD_IF_INDICES):
			inout = "%d\t%d" %(flow.if_ndx_in, flow.if_ndx_out)
			self.in_out_if.update(inout, flow)
	
	def update24(self, flow):
		if flow.has_field(flowd.FIELD_SRC_ADDR):
			self.src_prefix.update(self.net(flow.src_addr, flow.src_mask), flow)
	
	def update25(self, flow):
		if flow.has_field(flowd.FIELD_DST_ADDR):
			self.dst_prefix.update(self.net(flow.dst_addr, flow.dst_mask), flow)
	
	def update26(self, flow):
		if flow.has_field(flowd.FIELD_SRC_ADDR) and \
		   flow.has_field(flowd.FIELD_DST_ADDR):
			self.src_dst_prefix.update(self.net(flow.src_addr, flow.src_mask)+"\t"+self.net(flow.dst_addr, flow.dst_mask), flow)
	
	def update27(self, flow):
		if flow.has_field(flowd.FIELD_AGENT_ADDR):
			self.agent_addr.update(flow.agent_addr, flow)
	
	def update28(self, flow):
		if flow.has_field(flowd.FIELD_FLOW_ENGINE_INFO):
			self.engine_id.update(flow.engine_id, flow)
	
	def update29(self, flow):
		if flow.has_field(flowd.FIELD_FLOW_ENGINE_INFO):
			self.engine_type.update(flow.engine_type, flow)
	
	def update30(self, flow):
		if flow.has_field(flowd.FIELD_TAG):
			self.tag.update(flow.tag, flow)
	
	
	def update(self, flow):
		self.flows += 1
		
		if flow.has_field(flowd.FIELD_RECV_TIME):
			
			if self.first is None or \
			   flow.recv_sec < self.first:
				self.first = flow.recv_sec
			if self.last is None or \
			   flow.recv_sec > self.last:
				self.last = flow.recv_sec
			if self.start is None or \
			   flow.flow_start < self.start:
				self.start = flow.flow_start
			if self.finish is None or \
			   flow.flow_finish > self.finish:
				self.finish = flow.flow_finish
			if self.time is None:
				self.time = flow.flow_finish - flow.flow_start
			if flow.has_field(flowd.FIELD_FLOW_TIMES):
				delta = flow.recv_sec - \
				    flow.flow_finish / 1000.0
				if self.average_clockskew is None:
					self.average_clockskew = delta
				self.average_clockskew_samples += 1
				new_offset = delta - self.average_clockskew
				self.average_clockskew += new_offset / \
				    self.average_clockskew_samples
				self.time += flow.flow_finish - flow.flow_start
		
		if flow.has_field(flowd.FIELD_OCTETS):
			if self.octets is None:
				self.octets = 0
			self.octets += flow.octets
			self.opf.update(flow.octets, flow)


		if flow.has_field(flowd.FIELD_PACKETS):
			if self.packets is None:
				self.packets = 0
			self.packets += flow.packets
			self.ppf.update(flow.packets, flow)
		
		if flow.has_field(flowd.FIELD_OCTETS) and \
		   flow.has_field(flowd.FIELD_PACKETS):
			if flow.packets != 0: 
				self.packsize.update((flow.octets / flow.packets), flow)


		if flow.has_field(flowd.FIELD_FLOW_TIMES) and \
		   flow.has_field(flowd.FIELD_FLOW_TIMES):
		   	duration = flow.flow_finish - \
			    flow.flow_start
			duration = int(duration / 1000) # milliseconds


		if flow.has_field(flowd.FIELD_SRC_ADDR):
			self.src_addr.update(flow.src_addr, flow)
			self.addr.update(flow.src_addr, flow)
			self.src_prefix.update(self.net(flow.src_addr, flow.src_mask), flow)

		if flow.has_field(flowd.FIELD_DST_ADDR):
			self.dst_addr.update(flow.dst_addr, flow)
			self.addr.update(flow.dst_addr, flow)
			self.dst_prefix.update(self.net(flow.dst_addr, flow.dst_mask), flow)

		if flow.has_field(flowd.FIELD_SRC_ADDR) and \
		   flow.has_field(flowd.FIELD_DST_ADDR):
		   	fromto = flow.src_addr + " -> " + \
				 flow.dst_addr
			self.fromto.update(fromto, flow)
			self.src_dst_prefix.update(self.net(flow.src_addr, flow.src_mask)+"\t"+self.net(flow.dst_addr, flow.dst_mask), flow)

		if flow.has_field(flowd.FIELD_GATEWAY_ADDR):
			self.gateway_addr.update(flow.gateway_addr, flow)
			
		if flow.has_field(flowd.FIELD_AGENT_ADDR):
			self.agent_addr.update(flow.agent_addr, flow)
	
		if flow.has_field(flowd.FIELD_IF_INDICES):
			self.in_if.update(flow.if_ndx_in, flow)
			self.out_if.update(flow.if_ndx_out, flow)
			inout = "%d\t%d" %(flow.if_ndx_in, flow.if_ndx_out)
			self.in_out_if.update(inout, flow)
			
		if flow.has_field(flowd.FIELD_AS_INFO):
			self.src_as.update(flow.src_as, flow)
			self.dst_as.update(flow.dst_as, flow)
			srcdstas = "%d\t%d" %(flow.src_as, flow.dst_as)
			self.src_dst_as.update(srcdstas, flow)
			
		if flow.has_field(flowd.FIELD_FLOW_ENGINE_INFO):
			self.engine_id.update(flow.engine_id, flow)
			self.engine_type.update(flow.engine_type, flow)
			
		if flow.has_field(flowd.FIELD_TAG):
			self.tag.update(flow.tag, flow)
		
		if flow.has_field(flowd.FIELD_SRCDST_PORT):
			self.src_port.update(flow.src_port, flow)
			self.port.update(flow.src_port, flow)

		if flow.has_field(flowd.FIELD_SRCDST_PORT):
			self.dst_port.update(flow.dst_port, flow)
			self.port.update(flow.dst_port, flow)

		if flow.has_field(flowd.FIELD_PROTO_FLAGS_TOS):
			self.protocol.update(flow.protocol, flow)
			self.tos.update(flow.tos, flow)
		

	def net(self, addr, mask):
		str = ""
		if addr.count('.') > 0:
			s = addr.split(".")
			if mask == 0:
				m = 32
			else:
				m = mask
			x = 32 - m
			a = x / 8
			b = x % 8
			c = 256 - (2 ** b)
			s[3-a] = int(s[3-a]) & c
			i = 4-a
			for d in s:
				if i < 4:
					s[i] = 0
					i += 1
			str = "%d.%d.%d.%d/%d" %(int(s[0]),int(s[1]),int(s[2]),int(s[3]),mask)
		
		elif addr.count(':') > 0:
			s = addr.split(":")
			i = 0
			for d in s:
				if d == '':
					s[i]='0'
					k = i
				i += 1
				
			l = len(s)
			i=k+1
			while i <= (k+8-l):
				s.insert(i, '0')
				i += 1	
			
			if mask == 0:
				m = 128
			else:
				m = mask
			x = 128 - m
			a = x / 16
			b = x % 16
			c = 65535 - (2 ** b)
			s[7-a] = int(s[7-a],16) & c
			s[7-a] = "%x"%s[7-a]
			i = 8-a
			for d in s:
				if i < 8:
					s[i] = '0'
					i += 1
			str = "%s:%s:%s:%s:%s:%s:%s:%s/%d" %(s[0],s[1],s[2],s[3],s[4],s[5],s[6],s[7],mask)
		return str
	
	def report0(self):
		str = ""
		str += "Total Flow                      : %d\n" %self.flows
		str += "Total Octets                    : %d\n" %self.octets
		str += "Total Packets                   : %d\n" %self.packets
		str += "Total Time (flows)              : %d\n" %self.time 
		str += "Duration of data (realtime)     : %d\n" %(self.last-self.first)
		str += "Duration of data (1/1000 secs)  : %d\n" %(self.finish-self.start)
		str += "Average flow time (1/1000 secs) : %f\n" %(self.time / float(self.flows)) 
		str += "Average packet size (octets)    : %.4f\n" %(float(self.octets) / self.packets)
		str += "Average flow size (octets)      : %.4f\n" %(float(self.octets) / self.flows) 
		str += "Average packets per flow        : %.4f\n" %(float(self.packets) / self.flows) 
		str += "Average flows / second (flow)   : %.4f\n" %(float(self.flows)/((self.finish-self.start)/1000))
		str += "Average flows / second (real)   : %.4f\n" %(float(self.flows)/(self.last-self.first))
		str += "Average Kbits / second (flow)   : %.4f\n" %((float(self.octets * 8)/1000)/((self.finish-self.start)/1000))
		str += "Average Kbits / second (real)   : %.4f\n" %((float(self.octets * 8)/1000)/(self.last-self.first))
		return str
	
	def report1(self):
		str = "Pkt size \tFlows \t\tOctets \t\tPackets\n"
		for pktsize in self.packsize.counts.keys():
			flows = self.packsize.counts[pktsize].flows
			octets = self.packsize.counts[pktsize].octets
			packets = self.packsize.counts[pktsize].packets
			str += "%d" %pktsize
			if pktsize > 9999999:
				str +="\t"
			else:
				str += "\t\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
	
	def report2(self):
		str = "Packets \tFlows \t\tOctets \t\tPackets\n"
		for pkt in self.ppf.counts.keys():
			flows = self.ppf.counts[pkt].flows
			octets = self.ppf.counts[pkt].octets
			packets = self.ppf.counts[pkt].packets
			str += "%d" %pkt
			if pkt > 9999999:
				str +="\t"
			else:
				str += "\t\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
		
	def report3(self):
		str = "Octets \t\tFlows \t\tOctets \t\tPackets\n"
		for oct in self.opf.counts.keys():
			flows = self.opf.counts[oct].flows
			octets = self.opf.counts[oct].octets
			packets = self.opf.counts[oct].packets
			str += "%d" %oct
			if oct > 9999999:
				str +="\t"
			else:
				str += "\t\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
	
	def report4(self):
		return "not implemented"
	
	def report5(self):
		str = "dst port \tFlows \t\tOctets \t\tPackets\n"
		for port in self.dst_port.counts.keys():
			flows = self.dst_port.counts[port].flows
			octets = self.dst_port.counts[port].octets
			packets = self.dst_port.counts[port].packets
			str += "%d" %port
			if port > 9999999:
				str +="\t"
			else:
				str += "\t\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
	
	def report6(self):
		str = "src port \tFlows \t\tOctets \t\tPackets\n"
		for port in self.src_port.counts.keys():
			flows = self.src_port.counts[port].flows
			octets = self.src_port.counts[port].octets
			packets = self.src_port.counts[port].packets
			str += "%d" %port
			if port > 9999999:
				str +="\t"
			else:
				str += "\t\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
	
	def report7(self):
		str = "port \t\tFlows \t\tOctets \t\tPackets\n"
		for port in self.port.counts.keys():
			flows = self.port.counts[port].flows
			octets = self.port.counts[port].octets
			packets = self.port.counts[port].packets
			str += "%d" %port
			if port > 9999999:
				str +="\t"
			else:
				str += "\t\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
	
	def report8(self):
		str = "DST IP address \t\t\t\b Flows \t\t\b Octets \t\t\b Packets\n"
		for addr in self.dst_addr.counts.keys():
			flows = self.dst_addr.counts[addr].flows
			octets = self.dst_addr.counts[addr].octets
			packets = self.dst_addr.counts[addr].packets
			str += addr
			if len(addr) < 8:
				str +="\t\t\t\t"
			else:
				if len(addr) < 16:
					str +="\t\t\t"
				else:
					if len (addr) < 24:
						str +="\t\t"
					else: str += "\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
		
	def report9(self):
		str = "SRC IP address \t\t\t\b Flows \t\t\b Octets \t\t\b Packets\n"
		for addr in self.src_addr.counts.keys():
			flows = self.src_addr.counts[addr].flows
			octets = self.src_addr.counts[addr].octets
			packets = self.src_addr.counts[addr].packets
			str += addr
			if len(addr) < 8:
				str +="\t\t\t\t"
			else:
				if len(addr) < 16:
					str +="\t\t\t"
				else:
					if len (addr) < 24:
						str +="\t\t"
					else: str += "\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
		
	def report10(self):
		str = "SRC IP -> DST IP \t\t\t\b Flows \t\t\b Octets \t\t\b Packets\n"
		for addr in self.fromto.counts.keys():
			flows = self.fromto.counts[addr].flows
			octets = self.fromto.counts[addr].octets
			packets = self.fromto.counts[addr].packets
			str += addr
			if len(addr) < 24:
				str +="\t\t\t"
			else:
				if len(addr) < 32:
					str +="\t\t"
				else:
					if len (addr) < 40:
						str +="\t"
					else: str += "\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str	
		
	def report11(self):
		str = "IP address \t\t\t\b Flows \t\t\b Octets \t\t\b Packets\n"
		for addr in self.addr.counts.keys():
			flows = self.addr.counts[addr].flows
			octets = self.addr.counts[addr].octets
			packets = self.addr.counts[addr].packets
			str += addr
			if len(addr) < 8:
				str +="\t\t\t\t\t"
			else:
				if len(addr) < 16:
					str +="\t\t\t"
				else:
					if len (addr) < 24:
						str +="\t\t"
					else: str += "\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
		
	def report12(self):
		str = "protocol \tFlows \t\tOctets \t\tPackets\n"
		for proto in self.protocol.counts.keys():
			flows = self.protocol.counts[proto].flows
			octets = self.protocol.counts[proto].octets
			packets = self.protocol.counts[proto].packets
			str += "%d" %proto
			if proto > 9999999:
				str +="\t"
			else:
				str += "\t\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
	
	def report13(self, flow):
		str = ""
		if self.k == 0:
			str += "start \t\toctets \nend \t\toctets\n"
			self.k = 1
		if flow.has_field(flowd.FIELD_FLOW_TIMES) and \
		   flow.has_field(flowd.FIELD_OCTETS):
			str += "%d \t\t%d \n%d \t\t%d\n\n" %(flow.flow_start, flow.octets, flow.flow_finish, flow.octets) 
		return str
	
	def report14(self, flow):
		str = ""
		if self.k == 0:
			str += "start \t\tpackets \nend \t\tpackets\n"
			self.k = 1
		if flow.has_field(flowd.FIELD_FLOW_TIMES) and \
		   flow.has_field(flowd.FIELD_PACKETS):
			str += "%d \t\t%d \n%d \t\t%d\n\n" %(flow.flow_start, flow.packets, flow.flow_finish, flow.packets) 
		return str
	
	def report15(self):
		str = "Octets \t\tPackets \t\tMBytes\n"
		str += "%d \t" %self.octets
		str += "%d \t\t" %self.packets
		str += "%.3f" %(float(self.octets)/1000000)
		return str
		
	def report16(self):
		str = "IP address \t\t\t\b Flows \t\t\b Octets \t\t\b Packets\n"
		for addr in self.gateway_addr.counts.keys():
			flows = self.gateway_addr.counts[addr].flows
			octets = self.gateway_addr.counts[addr].octets
			packets = self.gateway_addr.counts[addr].packets
			str += addr
			if len(addr) < 8:
				str +="\t\t\t\t"
			else:
				if len(addr) < 16:
					str +="\t\t\t"
				else:
					if len (addr) < 24:
						str +="\t\t"
					else: str += "\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
		
	def report17(self):
		str = "interface \tFlows \t\tOctets \t\tPackets\n"
		for iface in self.in_if.counts.keys():
			flows = self.in_if.counts[iface].flows
			octets = self.in_if.counts[iface].octets
			packets = self.in_if.counts[iface].packets
			str += "%d" %iface
			if iface > 9999999:
				str +="\t"
			else:
				str += "\t\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
		
	def report18(self):
		str = "interface \tFlows \t\tOctets \t\tPackets\n"
		for iface in self.out_if.counts.keys():
			flows = self.out_if.counts[iface].flows
			octets = self.out_if.counts[iface].octets
			packets = self.out_if.counts[iface].packets
			str += "%d" %iface
			if iface > 9999999:
				str +="\t"
			else:
				str += "\t\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
		
	def report23(self):
		str = "in \tout \t\tFlows \t\tOctets \t\tPackets\n"
		for iface in self.in_out_if.counts.keys():
			flows = self.in_out_if.counts[iface].flows
			octets = self.in_out_if.counts[iface].octets
			packets = self.in_out_if.counts[iface].packets
			str += "%s" %iface
			if len(iface) > 7:
				str +="\t"
			else:
				str += "\t\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
		
	def report19(self):
		str = "src as \t\tFlows \t\tOctets \t\tPackets\n"
		for asys in self.src_as.counts.keys():
			flows = self.src_as.counts[asys].flows
			octets = self.src_as.counts[asys].octets
			packets = self.src_as.counts[asys].packets
			str += "%d" %asys
			if asys > 9999999:
				str +="\t"
			else:
				str += "\t\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
		
	def report20(self):
		str = "dst as \t\tFlows \t\tOctets \t\tPackets\n"
		for asys in self.dst_as.counts.keys():
			flows = self.dst_as.counts[asys].flows
			octets = self.dst_as.counts[asys].octets
			packets = self.dst_as.counts[asys].packets
			str += "%d" %asys
			if asys > 9999999:
				str +="\t"
			else:
				str += "\t\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
		
	def report21(self):
		str = "src as\tdst as \t\tFlows \t\tOctets \t\tPackets\n"
		for asys in self.src_dst_as.counts.keys():
			flows = self.src_dst_as.counts[asys].flows
			octets = self.src_dst_as.counts[asys].octets
			packets = self.src_dst_as.counts[asys].packets
			str += "%s" %asys
			if len(asys) > 7:
				str +="\t"
			else:
				str += "\t\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
		
	def report22(self):
		str = "ToS \t\tFlows \t\tOctets \t\tPackets\n"
		for tos in self.tos.counts.keys():
			flows = self.tos.counts[tos].flows
			octets = self.tos.counts[tos].octets
			packets = self.tos.counts[tos].packets
			str += "%d" %tos
			if tos > 9999999:
				str +="\t"
			else:
				str += "\t\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
		
	def report24(self):
		str = "Source prefix \t\t\t\t\b Flows \t\t\b Octets \t\t\b Packets\n"
		for addr in self.src_prefix.counts.keys():
			flows = self.src_prefix.counts[addr].flows
			octets = self.src_prefix.counts[addr].octets
			packets = self.src_prefix.counts[addr].packets
			str += addr
			if len(addr) < 8:
				str +="\t\t\t\t\t"
			elif len(addr) < 16:
				str +="\t\t\t\t"
			elif len (addr) < 24:
				str +="\t\t\t"
			elif len(addr) < 32:
				str += "\t\t"
			else:
				str += "\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str	
	
	def report25(self):
		str = "Destination prefix \t\t\t\b Flows \t\t\b Octets \t\t\b Packets\n"
		for addr in self.dst_prefix.counts.keys():
			flows = self.dst_prefix.counts[addr].flows
			octets = self.dst_prefix.counts[addr].octets
			packets = self.dst_prefix.counts[addr].packets
			str += addr
			if len(addr) < 8:
				str +="\t\t\t\t\t"
			elif len(addr) < 16:
				str +="\t\t\t\t"
			elif len (addr) < 24:
				str +="\t\t\t"
			elif len(addr) < 32:
				str += "\t\t"
			else:
				str += "\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str	
		
	def report26(self):
		str = "Source prefix \t\tDestination prefix \n\t\tFlows \t\tOctets \t\tPackets\n"
		for addr in self.src_dst_prefix.counts.keys():
			flows = self.src_dst_prefix.counts[addr].flows
			octets = self.src_dst_prefix.counts[addr].octets
			packets = self.src_dst_prefix.counts[addr].packets
			str += addr+"\n\t\t"
			
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str	
		
	def report27(self):
		str = "IP address \t\t\t\b Flows \t\t\b Octets \t\t\b Packets\n"
		for addr in self.agent_addr.counts.keys():
			flows = self.agent_addr.counts[addr].flows
			octets = self.agent_addr.counts[addr].octets
			packets = self.agent_addr.counts[addr].packets
			str += addr
			if len(addr) < 8:
				str +="\t\t\t\t"
			else:
				if len(addr) < 16:
					str +="\t\t\t"
				else:
					if len (addr) < 24:
						str +="\t\t"
					else: str += "\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
		
	def report28(self):
		str = "engine_id \tFlows \t\tOctets \t\tPackets\n"
		for engine in self.engine_id.counts.keys():
			flows = self.engine_id.counts[engine].flows
			octets = self.engine_id.counts[engine].octets
			packets = self.engine_id.counts[engine].packets
			str += "%d" %engine
			if engine > 9999999:
				str +="\t"
			else:
				str += "\t\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
		
	def report29(self):
		str = "engine_type \tFlows \t\tOctets \t\tPackets\n"
		for engine in self.engine_type.counts.keys():
			flows = self.engine_type.counts[engine].flows
			octets = self.engine_type.counts[engine].octets
			packets = self.engine_type.counts[engine].packets
			str += "%d" %engine
			if engine > 9999999:
				str +="\t"
			else:
				str += "\t\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
		
	def report30(self):
		str = "tag \t\tFlows \t\tOctets \t\tPackets\n"
		for tag in self.tag.counts.keys():
			flows = self.tag.counts[tag].flows
			octets = self.tag.counts[tag].octets
			packets = self.tag.counts[tag].packets
			str += "%d" %tag
			if tag > 9999999:
				str +="\t"
			else:
				str += "\t\t"
			str += "%d" %flows
			if flows > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %octets
			if octets > 9999999: 
				str += "\t"
			else:
				str += "\t\t"
			str += "%d" %packets
			str += "\n"
		return str
		
def usage():
	print >> sys.stderr, "stat.py (flowd.py version %s)" % \
	    flowd.__version__
	print >> sys.stderr, "Usage: stats.py [options] [flowd-store]";
	print >> sys.stderr, "Options:";
	print >> sys.stderr, "      -h       Display this help";
	print >> sys.stderr, "      -f       Format of output (like flow-stat from flow-tools). Default 0";
	print >> sys.stderr, "      -p       pickle_file";
	print >> sys.stderr, "      -o       output_file";
#	print >> sys.stderr, "      	Report format.  Choose from the following:";
#	print >> sys.stderr, "      	    0  Overall Summary";
#	print >> sys.stderr, "      	 	1  Average packet size distribution";
#	print >> sys.stderr, "      		2  Packets per flow distribution";
#	print >> sys.stderr, "      		3  Octets per flow distribution";
#	print >> sys.stderr, "      		4  Bandwidth per flow distribution";
#	print >> sys.stderr, "      		5  UDP/TCP destination port";
#	print >> sys.stderr, "      		6  UDP/TCP source port";
#	print >> sys.stderr, "      		7  UDP/TCP port";
#	print >> sys.stderr, "      		8  Destination IP";
#	print >> sys.stderr, "      		9  Source IP";
#	print >> sys.stderr, "      		10 Source/Destination IP";
#	print >> sys.stderr, "      		11 Source or Destination IP";
#	print >> sys.stderr, "      		12 IP protocol";
#	print >> sys.stderr, "      		13 octets for flow duration plot data";
#	print >> sys.stderr, "      		14 packets for flow duration plot data";
#	print >> sys.stderr, "      		15 short summary";
#	print >> sys.stderr, "      		16 IP Next Hop";
#	print >> sys.stderr, "      		17 Input interface";
#	print >> sys.stderr, "      		18 Output interface";
#	print >> sys.stderr, "      		19 Source AS";
#	print >> sys.stderr, "      		20 Destination AS";
#	print >> sys.stderr, "      		21 Source/Destination AS";
#	print >> sys.stderr, "      		22 IP ToS";
#	print >> sys.stderr, "      		23 Input/Output Interface";
#	print >> sys.stderr, "      		24 Source Prefix";
#	print >> sys.stderr, "      		25 Destination Prefix";
#	print >> sys.stderr, "      		26 Source/Destination Prefix";
#	print >> sys.stderr, "      		27 Exporter IP";
#	print >> sys.stderr, "      		28 Engine Id";
#	print >> sys.stderr, "      		29 Engine Type";
#	print >> sys.stderr, "      		30 Tag";
	sys.exit(1);

def main():
	stats = flow_statistics()

	try:
		opts, args = getopt.getopt(sys.argv[1:], 'f:p:o:h')
	except getopt.GetoptError:
		print >> sys.stderr, "Invalid commandline arguments"
		usage()

	outformat = None
	pickle_file = None
	output_file = None
	for o, a in opts:
		if o in ('-h', '--help'):
			usage()
			sys.exit(0)
		if o in ('-f', '--format'):
			outformat = a
		if o in ('-p', '--pickle'):
			pickle_file = a
		if o in ('-o', '--output'):
			output_file = a
	
	if len(args) == 0:
		print >> sys.stderr, "No logfiles specified"
		usage()
		
	if outformat is None:
		outformat = 0
	elif not outformat.isdigit() or int(outformat) > 30:
		print >> sys.stderr, "Invalid format"
		usage()
		
	if output_file is not None:
		out = open(output_file, "w")
	
	print "report #"+outformat
	#if output_file is not None:
	#	out.write("report #"+outformat)
	#print dir(flowd)
		
	for ffile in args:
		if ffile == "-":
			flog = flowd.FlowLog_fromfile(sys.stdin)
		else:
			flog = flowd.FlowLog(ffile, "rb")
		for flow in flog:
			#stats.update(flow)
			if outformat == '0':
				stats.update0(flow)
			elif outformat == '1':
				stats.update1(flow)
			elif outformat == '2':
				stats.update2(flow)
			elif outformat == '3':
				stats.update3(flow)
			elif outformat == '5':
				stats.update5(flow)
			elif outformat == '6':
				stats.update6(flow)
			elif outformat == '7':
				stats.update7(flow)
			elif outformat == '8':
				stats.update8(flow)
			elif outformat == '9':
				stats.update9(flow)
			elif outformat == '10':
				stats.update10(flow)
			elif outformat == '11':
				stats.update11(flow)
			elif outformat == '12':
				stats.update12(flow)
			elif outformat == '13':
				print stats.report13(flow)
				if output_file is not None:
					out.write(stats.report13(flow))
			elif outformat == '14':
				print stats.report14(flow)
				if output_file is not None:
					out.write(stats.report14(flow))
			elif outformat == '15':
				stats.update15(flow)
			elif outformat == '16':
				stats.update16(flow)
			elif outformat == '17':
				stats.update17(flow)
			elif outformat == '18':
				stats.update18(flow)
			elif outformat == '19':
				stats.update19(flow)
			elif outformat == '20':
				stats.update20(flow)
			elif outformat == '21':
				stats.update21(flow)
			elif outformat == '22':
				stats.update22(flow)
			elif outformat == '23':
				stats.update23(flow)
			elif outformat == '24':
				stats.update24(flow)
			elif outformat == '25':
				stats.update25(flow)
			elif outformat == '26':
				stats.update26(flow)
			elif outformat == '27':
				stats.update27(flow)
			elif outformat == '28':
				stats.update28(flow)
			elif outformat == '29':
				stats.update29(flow)
			elif outformat == '30':
				stats.update30(flow)
			
	if outformat == '0':
		print stats.report0()
		if output_file is not None:
			out.write(stats.report0())
	elif outformat == '1':
		print stats.report1()
		if output_file is not None:
			out.write(stats.report1())
	elif outformat == '2':
		print stats.report2()
		if output_file is not None:
			out.write(stats.report2())
	elif outformat == '3':
		print stats.report3()
		if output_file is not None:
			out.write(stats.report3())
	elif outformat == '4':
		print stats.report4()
		if output_file is not None:
			out.write(stats.report4())
	elif outformat == '5':
		print stats.report5()
		if output_file is not None:
			out.write(stats.report5())
	elif outformat == '6':
		print stats.report6()
		if output_file is not None:
			out.write(stats.report6())
	elif outformat == '7':
		print stats.report7()
		if output_file is not None:
			out.write(stats.report7())
	elif outformat == '8':
		print stats.report8()
		if output_file is not None:
			out.write(stats.report8())
	elif outformat == '9':
		print stats.report9()
		if output_file is not None:
			out.write(stats.report9())
	elif outformat == '10':
		print stats.report10()
		if output_file is not None:
			out.write(stats.report10())
	elif outformat == '11':
		print stats.report11()
		if output_file is not None:
			out.write(stats.report11())
	elif outformat == '12':
		print stats.report12()
		if output_file is not None:
			out.write(stats.report12())
	elif outformat == '15':
		print stats.report15()
		if output_file is not None:
			out.write(stats.report15())
	elif outformat == '16':
		print stats.report16()
		if output_file is not None:
			out.write(stats.report16())
	elif outformat == '17':
		print stats.report17()
		if output_file is not None:
			out.write(stats.report17())
	elif outformat == '18':
		print stats.report18()
		if output_file is not None:
			out.write(stats.report18())
	elif outformat == '19':
		print stats.report19()
		if output_file is not None:
			out.write(stats.report19())
	elif outformat == '20':
		print stats.report20()
		if output_file is not None:
			out.write(stats.report20())
	elif outformat == '21':
		print stats.report21()
		if output_file is not None:
			out.write(stats.report21())
	elif outformat == '22':
		print stats.report22()
		if output_file is not None:
			out.write(stats.report22())
	elif outformat == '23':
		print stats.report23()
		if output_file is not None:
			out.write(stats.report23())
	elif outformat == '24':
		print stats.report24()
		if output_file is not None:
			out.write(stats.report24())
	elif outformat == '25':
		print stats.report25()
		if output_file is not None:
			out.write(stats.report25())
	elif outformat == '26':
		print stats.report26()
		if output_file is not None:
			out.write(stats.report26())
	elif outformat == '27':
		print stats.report27()
		if output_file is not None:
			out.write(stats.report27())
	elif outformat == '28':
		print stats.report28()
		if output_file is not None:
			out.write(stats.report28())
	elif outformat == '29':
		print stats.report29()
		if output_file is not None:
			out.write(stats.report29())
	elif outformat == '30':
		print stats.report30()
		if output_file is not None:
			out.write(stats.report30())
		
	if output_file is not None:
		out.close()	
		print "Statistics stored to \"%s\"" % \
		    output_file
	
	if pickle_file is not None:
		out = open(pickle_file, "wb")
		pickle.dump(stats, out)
		out.close()
		print >> sys.stderr, "Statistics pickled to \"%s\"" % \
		    pickle_file
			
if __name__ == '__main__': main()